package com.yonyou.iuap.ipaas.connector.sdwcoatencent.internal;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.asinking.com.openapi.sdk.core.HttpMethod;
import com.asinking.com.openapi.sdk.core.HttpRequest;
import com.asinking.com.openapi.sdk.core.HttpResponse;
import com.asinking.com.openapi.sdk.okhttp.AKRestClientBuild;
import com.asinking.com.openapi.sdk.okhttp.HttpExecutor;
import com.asinking.com.openapi.sdk.sign.ApiSign;
import com.yonyou.iuap.ipaas.cache.api.Consistency;
import com.yonyou.iuap.ipaas.cache.core.CacheContext;
import com.yonyou.iuap.ipaas.cache.core.CacheService;
import com.yonyou.iuap.ipaas.connector.sdk.api.model.ConnectorParams;
import com.yonyou.iuap.ipaas.connector.sdk.api.model.ResponseAttributes;
import com.yonyou.iuap.ipaas.connector.sdk.internal.connection.CoreConnection;
import com.yonyou.iuap.ipaas.connector.sdwcoatencent.api.model.common.PageableData;
import com.yonyou.iuap.ipaas.connector.sdwcoatencent.api.model.core.constant.ApiConstants;
import com.yonyou.iuap.ipaas.connector.sdwcoatencent.internal.exception.ExecuteException;
import com.yonyou.iuap.ipaas.connector.sdwcoatencent.internal.utils.JSON;
import com.yonyou.iuap.ipaas.connector.sdwcoatencent.internal.utils.LogUtil;
import com.yonyou.yonlinker.ysb.runtime.api.connection.ConnectionValidationResult;
import com.yonyou.yonlinker.ysb.runtime.extension.api.runtime.operation.Result;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 此类表示扩展连接
 */
@Getter
public final class LxwcoatencentConnection implements CoreConnection {

    private static Logger logger = LoggerFactory.getLogger(LxwcoatencentConnection.class);

    public static final CacheService cacheService = CacheService.getCacheService();
    private static final Long TIME = 7200L;
    private String host;

    private String appSecret;

    private String appKey;

    private String outerHost;
    public String getOuterHost() {
        return outerHost;
    }
    /**
     * 构造函数
     *
     */
    public LxwcoatencentConnection(String appKey, String appSecret, String host,String outerHost) {
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.host = host;
        this.outerHost = outerHost;
    }

    @Override
    public void invalidate() {
        //此处可以写一些处理断开连接后的事项代码；
        String cacheKey = "token:" + appKey;
        //String cacheKey = "token:";
        cacheService.evict(cacheKey);
        logger.error("【领星连接器】accessToken已清除");
    }

    @Override
    public ConnectionValidationResult validate() {
        return null;
    }
    
    static {
        CacheContext cacheContext = new CacheContext();
        cacheContext.setPushMessage(false);
        cacheContext.setConsistency(Consistency.strict);
        cacheContext.setRunPolicy("redis");
        cacheContext.setConnectorMainClass(SdwcoatencentExtension.class);
        CacheService.initContext(cacheContext);
    }

    public PageableData doQuery(String path, JSONObject body){
        if (body!=null){
            if (body.get("page")!=null){
                Integer offset = body.getInt("page");
                //做判断
                int realityPageNo = offset - 1;
                if (realityPageNo < 0) {
                    realityPageNo = offset;
                }
                body.set("page",realityPageNo);
            }else if (body.get("offset")!=null){
                Integer offset = body.getInt("offset");
                //做判断
                int realityPageNo = offset - 1;
                if (realityPageNo < 0) {
                    realityPageNo = offset;
                }
                body.set("offset",realityPageNo);
            }
        }

        // 基本请求参数
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("timestamp", System.currentTimeMillis() / 1000 + "");
        queryParam.put("app_key", appKey);
        try {
//            String lxToken = getLxToken(appKey, appSecret, host);
            //  queryParam.put("access_token", "31689571-4d0f-4e72-a0d3-d699742419d9");
             queryParam.put("access_token", getLxToken(appKey, appSecret, host));
        } catch (Exception e) {
            throw ExecuteException.serverResponseError("token获取失败"+e.getMessage());
        }
        if (body!=null){
            MapListToStr(body, queryParam);
        }

        String sign = ApiSign.lxSign(queryParam, appKey);
        queryParam.put("sign", sign);

        HttpRequest<Object> build = HttpRequest.builder(Object.class)
                .method(HttpMethod.POST)
                .endpoint(host)
                .path(path)
                .queryParams(queryParam)
                .json(JSONUtil.toJsonStr(body))
                .build();
        HttpResponse execute = null;
        try {
            execute = HttpExecutor.create().execute(build);
        } catch (Exception e) {
            throw ExecuteException.serverResponseError("查询失败"+e.getMessage());
        }
        JSONObject resJson = execute.readEntity(JSONObject.class);
        System.out.println("查询结果:"+JSONUtil.toJsonStr(resJson));
        PageableData<Object> pageableData = new PageableData<>();
        if("0".equals(resJson.getStr("code"))){
            Integer totalCount ;
            JSONArray datas;
            if (resJson.containsKey("total")){
                totalCount = resJson.getInt("total");
                datas = resJson.getJSONArray("data");
            }else {
                totalCount = resJson.getJSONObject("data").getInt("total");
                datas = resJson.getJSONObject("data").getJSONArray("list");
            }

            if (totalCount==0){
                totalCount=datas.size();
            }
            Integer pageIndex=1;
            Integer pageSize=20;
            pageableData.setDatas(datas);
            if (body!=null){
                 pageIndex = MapUtil.getInt(body, "offset")+1;
                if (body.get("page")!=null){
                    pageIndex = MapUtil.getInt(body, "page")+1;
                }
                 pageSize = MapUtil.getInt(body, "length");
                if (body.get("page_size")!=null){
                    pageSize = MapUtil.getInt(body, "page_size");
                }
            }else {
                pageSize=totalCount;
            }

            pageableData.setPageSize(pageSize);
            pageableData.setPageIndex(pageIndex);
            if (body==null){
                pageableData.setPageCount(1);
                pageableData.setDataCount(totalCount);
            }else {
                if (totalCount!=null){
                    pageableData.setDataCount(totalCount);
                    Integer pageConunt = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
                    pageableData.setPageCount(pageConunt);
                }
            }
        }
        return pageableData;
    }

    private void MapListToStr(Map<String, Object> body, Map<String, Object> queryParam) {
        for (String key : body.keySet()) {
            if (body.get(key) instanceof List || body.get(key) instanceof ArrayList || body.get(key) instanceof JSONArray){
                queryParam.put(key, JSONUtil.toJsonStr(body.get(key)));
            }else {
                queryParam.put(key,body.get(key));
            }
        }
    }
    public String getLxToken(String appKey,String appSecret,String endpoint) throws Exception {
        String cacheKey = "token:" + appKey;
        String access_tokenKey = "access_token" ;
        String refresh_tokenKey = "refresh_token" ;
        String token = "";
        Object cacheValue = cacheService.get(cacheKey);
        if (cacheValue == null) {
            com.asinking.com.openapi.sdk.entity.Result result = AKRestClientBuild.builder().endpoint(endpoint).getAccessToken(appKey, appSecret);
            System.out.println(JSONUtil.toJsonStr(result));
            Map<String, Object> resultData = (Map<String, Object>) result.getData();
            token = (String)resultData.get(access_tokenKey);
            cacheService.put(cacheKey, resultData.get(access_tokenKey)+"@"+resultData.get(refresh_tokenKey)+"@"+System.currentTimeMillis(), TIME);
//            cacheService.put(refresh_tokenKey, resultData.get(refresh_tokenKey), time);
        } else {
            String[] cacheValueArr = Convert.toStr(cacheValue).split("@");
            String accessToken = cacheValueArr[0];
            String refreshToken = cacheValueArr[1];
            // 当前时间戳-缓存刚存进去的时间戳 为 访问令牌已消耗的过期时间
            long startTimeMillis = System.currentTimeMillis() - Long.parseLong(cacheValueArr[2]);
            if (startTimeMillis < 1800*1000) {
                // 如果用postman等其他工具调试时，需要将appSecret用urlencode.encode()进行转义
                Map<String, Object> resultRefreshData = (Map<String, Object>)AKRestClientBuild.builder().endpoint(endpoint).refreshToken(appKey, refreshToken);
                Map<String, Object> resultRefresh =(Map<String, Object>)resultRefreshData.get("data");
                token = (String)resultRefresh.get(access_tokenKey);
                cacheService.put(cacheKey, resultRefresh.get(access_tokenKey)+"@"+resultRefresh.get(refresh_tokenKey)+"@"+System.currentTimeMillis(), TIME);
//                cacheService.put(refresh_tokenKey, resultRefresh.get(refresh_tokenKey), time);
            } else {
                token = accessToken;
            }
        }
        return token;
    }

    public Result<String, ResponseAttributes> returnCommonResult(String methodName, PageableData result) {
        Result.Builder<String, ResponseAttributes> builder = Result.builder();
        ResponseAttributes ra = new ResponseAttributes();
        ra.setSuccess(true);
        ra.setCode("0");
        ra.setMessage("成功");
        long pageIndex = 1L;
        long pageSize = 10L;
        long total = 1000L;
        if (result.getPageIndex() != null) {
            pageIndex = result.getPageIndex();
        }
        if (result.getPageSize() != null) {
            pageSize = result.getPageSize();
        }
        if (result.getDataCount() != null) {
            total = result.getDataCount();
        }
        if (ObjectUtil.isEmpty(result.getDatas())) {
            // 如果没有返回数据，总数直接返回0
            total = 0L;
        }
        ra.setPageIndex(pageIndex);
        ra.setPageSize(pageSize);
        ra.setTotalCount(total);
        if (result.getHasNext() != null) {
            ra.setHaveNextPage(result.getHasNext());
        } else {
            ra.setHaveNextPage(total > pageIndex * pageSize);
        }
        String output = JSON.writeValueAsString(result.getDatas());
        builder.output(output);
        Result<String, ResponseAttributes> returnResult = builder.attributes(ra).build();
        LogUtil.end(logger, methodName, returnResult);
        return returnResult;
    }

    public static final String aesKey = "lxConnectordas8fas54tsadf213s121";
    public static final SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes(CharsetUtil.CHARSET_UTF_8));

    public String doSecurePost(String url, String materialSyncRequests) {
        try {
            Map<String, Object> postBody = new HashMap<>();
            postBody.put("biz", materialSyncRequests);
            postBody.put("host", this.host);
            postBody.put("app_key", this.appKey);
            postBody.put("app_secret", this.appSecret);
            postBody.put("access_token", this.getAccessToken());
            // 加密为16进制表示
            String encryptParam = aes.encryptHex(JSONUtil.toJsonStr(postBody));
            postBody.clear();
            postBody.put("postBody", encryptParam);
            // 设置超时
            LogUtil.apiInfo(logger, this.outerHost + url, "领星中间服务调用参数：" + postBody);
            String resultStr = HttpUtil.post(getOuterHost() + url, postBody, ApiConstants.HTTP_CONNECT_TIMEOUT_MILLISECOND);
            System.out.println(resultStr);
            if (!JSONUtil.isTypeJSON(resultStr)) {
                throw ExecuteException.serverResponseError("领星服务请求异常：返回值非JSON结构");
            }
            JSONObject resultJson = JSONUtil.parseObj(resultStr);
            if (resultJson.containsKey("code") && !"200".equals(resultJson.getStr("code"))) {
                throw ExecuteException.serverResponseError("领星服务请求异常：" + resultJson.getStr("msg"));
            } else {
                resultStr = resultJson.getStr("content");
            }
            LogUtil.apiInfo(logger, getOuterHost() + url, "领星中间服务返回结果：" + resultStr);
            return resultStr;
        } catch (Exception e) {
            throw ExecuteException.serverResponseError("领星服务请求异常：" + e.getMessage());
        }
    }

    private String getAccessToken() {
        return null;
    }
}
